package com.arsn.myf.flow.service.impl;

import com.arsn.myf.common.util.StringUtils;
import com.arsn.myf.common.util.auth.AuthUtil;
import com.arsn.myf.common.util.date.DateUtils;
import com.arsn.myf.flow.entity.Flow;
import com.arsn.myf.flow.service.CommonTaskService;
import com.arsn.myf.system.entity.User;
import com.arsn.myf.system.service.UserService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.flowable.engine.HistoryService;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.ui.common.security.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 任务接口实现层
 * @author zhongrj
 * @since 2022-11-04
 */
@Service
public class CommonTaskServiceImpl implements CommonTaskService{

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private org.flowable.engine.TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private UserService userService;

    /**
     * 已发事务列表页
     * @param page
     * @param flow
     * @return
     */
    @Override
    public IPage<Flow> selectSendPage(Page<Flow> page, Flow flow) {

        List<Flow> flowList = new LinkedList<>();

        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
                .startedBy(AuthUtil.getUserId().toString())
                .orderByProcessInstanceStartTime()
                .desc();

        //设置查询参数
        if(!StringUtils.isBlank(flow.getTaskName())){
            historicProcessInstanceQuery.processDefinitionName("%"+flow.getTaskName()+"%");
        }

        Long current = page.getSize() * (page.getCurrent() - 1);
        Long size = page.getSize();
        List<HistoricProcessInstance> historicProcessInstanceList
                = historicProcessInstanceQuery.listPage(Integer.parseInt(current.toString()), Integer.parseInt(size.toString()));

        //遍历
        historicProcessInstanceList.forEach(historicProcessInstance -> {
            Flow flow0 = new Flow();
            // historicProcessInstance
            flow0.setCreateTime(historicProcessInstance.getStartTime());
            flow0.setEndTime(historicProcessInstance.getEndTime());
            flow0.setVariables(historicProcessInstance.getProcessVariables());
            //设置业务id
            if (null!= historicProcessInstance.getBusinessKey()) {
                String[] businessKey = historicProcessInstance.getBusinessKey().split(":");
                if (businessKey.length > 1) {
                    flow0.setBusinessTable(businessKey[0]);
                    flow0.setBusinessId(businessKey[1]);
                }
            }

            //流程发起人
            flow0.setCreateUserName(userService.getById(historicProcessInstance.getStartUserId()).getRealName());

            flow0.setHistoryActivityName(historicProcessInstance.getName());
            flow0.setProcessInstanceId(historicProcessInstance.getId());
            flow0.setHistoryProcessInstanceId(historicProcessInstance.getId());
            //查询流程定义信息
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(historicProcessInstance.getProcessDefinitionId())
                    .singleResult();

            flow0.setCategory(processDefinition.getCategory());
            flow0.setProcessDefinitionId(processDefinition.getId());
            flow0.setProcessDefinitionName(processDefinition.getName());
            flow0.setProcessDefinitionKey(processDefinition.getKey());
            flow0.setProcessDefinitionVersion(processDefinition.getVersion());
            flow0.setProcessInstanceId(historicProcessInstance.getId());

            // HistoricTaskInstance
            List<HistoricTaskInstance> historyTasks = historyService.createHistoricTaskInstanceQuery().
                    processInstanceId(historicProcessInstance.getId()).
                    orderByHistoricTaskInstanceEndTime().
                    desc().
                    list();
            if (null!=historyTasks) {
                HistoricTaskInstance historyTask = historyTasks.iterator().next();
                flow0.setTaskId(historyTask.getId());
                flow0.setTaskName(historyTask.getName());
                flow0.setTaskDefinitionKey(historyTask.getTaskDefinitionKey());
            }
            // Status
            if (historicProcessInstance.getEndActivityId() != null) {
                flow0.setProcessIsFinished("finished");
            } else {
                flow0.setProcessIsFinished("unfinished");
            }
            flow0.setStatus("finish");

            //加入集合
            flowList.add(flow0);
        });

        // 计算总数
        long count = historicProcessInstanceQuery.count();
        // 设置总数
        page.setTotal(count);
        // 设置数据
        page.setRecords(flowList);
        // 返回
        return page;
    }

    /**
     * 签收任务
     * @param taskId 任务id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean claimTask(String taskId) {
        //签收任务
        taskService.claim(taskId, AuthUtil.getUserId().toString());
        //返回
        return true;
    }

    /**
     * 完成任务
     * @param flow
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeTask(Flow flow) {
        Map<String, Object> map = new HashMap<>();
        map.put("pass",flow.getFlag().equals("1")?true:false);
        //如果任务意见不为null
        if (null!=flow.getComment() && !flow.getComment().equals("")){
            taskService.addComment(flow.getTaskId(),flow.getProcessInstanceId(),flow.getComment());
        }
        taskService.complete(flow.getTaskId(),map);
        //返回
        return true;
    }


    /**
     * 待签收事务列表页
     * @param page
     * @param flow
     * @return
     */
    @Override
    public IPage<Flow> selectClaimPage(Page<Flow> page, Flow flow) {
        //已角色为例，查询当前登录人员的角色
        String userRole = AuthUtil.getUserRole();
        //查询已签收的任务--候选组可以是按角色、部门
        TaskQuery taskQuery = taskService.createTaskQuery()
                .taskCandidateGroup(userRole)
                .includeProcessVariables()
                .active()
                .orderByTaskCreateTime()
                .desc();

        List<Flow> flowList = new LinkedList<>();

        //设置查询参数
        if(!StringUtils.isBlank(flow.getTaskName())){
            taskQuery.taskNameLike("%"+flow.getTaskName()+"%");
        }

        //遍历
        taskQuery.list().forEach(task -> {
            Flow flow0 = new Flow();
            flow0.setTaskId(task.getId());
            flow0.setTaskDefinitionKey(task.getTaskDefinitionKey());
            flow0.setTaskName(task.getName());
            flow0.setAssignee(task.getAssignee());
            flow0.setCreateTime(task.getCreateTime());
            flow0.setClaimTime(task.getClaimTime());
            flow0.setExecutionId(task.getExecutionId());
            flow0.setVariables(task.getProcessVariables());

            //获取历史流程实例信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .singleResult();
            if (null!=historicProcessInstance) {
                if (null!=historicProcessInstance.getBusinessKey()) {
                    String[] businessKey = historicProcessInstance.getBusinessKey().split(StringPool.COLON);
                    flow0.setBusinessTable(businessKey[0]);
                    flow0.setBusinessId(businessKey[1]);
                }
                //流程发起人
                flow0.setCreateUserName(userService.getById(historicProcessInstance.getStartUserId()).getRealName());
            }

            //查询流程定义信息
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(task.getProcessDefinitionId())
                    .singleResult();

            flow0.setCategory(processDefinition.getCategory());
            flow0.setProcessDefinitionId(processDefinition.getId());
            flow0.setProcessDefinitionName(processDefinition.getName());
            flow0.setProcessDefinitionKey(processDefinition.getKey());
            flow0.setProcessDefinitionVersion(processDefinition.getVersion());
            flow0.setProcessInstanceId(task.getProcessInstanceId());
            flow0.setStatus("claim");

            //加入集合
            flowList.add(flow0);
        });

        // 计算总数
        long count = taskQuery.count();
        // 设置总数
        page.setTotal(count);
        // 设置数据
        page.setRecords(flowList);
        //返回
        return page;
    }

    /**
     * 待处理事务列表页
     * @param page
     * @param flow
     * @return
     */
    @Override
    public IPage<Flow> selectTodoPage(Page<Flow> page, Flow flow) {
        //查询已签收的任务
        TaskQuery taskQuery = taskService.createTaskQuery()
                .taskCandidateOrAssigned(AuthUtil.getUserId().toString())
                .orderByTaskCreateTime()
                .desc();

        List<Flow> flowList = new LinkedList<>();

        //设置查询参数
        if(!StringUtils.isBlank(flow.getTaskName())){
            taskQuery.taskNameLike("%"+flow.getTaskName()+"%");
        }

        //遍历
        taskQuery.list().forEach(task -> {
            Flow flow0 = new Flow();
            flow0.setTaskId(task.getId());
            flow0.setTaskDefinitionKey(task.getTaskDefinitionKey());
            flow0.setTaskName(task.getName());
            flow0.setAssignee(task.getAssignee());
            flow0.setCreateTime(task.getCreateTime());
            flow0.setClaimTime(task.getClaimTime());
            flow0.setExecutionId(task.getExecutionId());
            flow0.setVariables(task.getProcessVariables());


            flow0.setAssigneeName(userService.getById(task.getAssignee()).getRealName());

            //获取历史流程实例信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .singleResult();
            if (null!=historicProcessInstance) {
                if (null!=historicProcessInstance.getBusinessKey()) {
                    String[] businessKey = historicProcessInstance.getBusinessKey().split(StringPool.COLON);
                    flow0.setBusinessTable(businessKey[0]);
                    flow0.setBusinessId(businessKey[1]);
                }
                //流程发起人
                flow0.setCreateUserName(userService.getById(historicProcessInstance.getStartUserId()).getRealName());
            }

            //查询流程定义信息
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(task.getProcessDefinitionId())
                    .singleResult();

            flow0.setCategory(processDefinition.getCategory());
            flow0.setProcessDefinitionId(processDefinition.getId());
            flow0.setProcessDefinitionName(processDefinition.getName());
            flow0.setProcessDefinitionKey(processDefinition.getKey());
            flow0.setProcessDefinitionVersion(processDefinition.getVersion());
            flow0.setProcessInstanceId(task.getProcessInstanceId());
            flow0.setStatus("todo");

            //加入集合
            flowList.add(flow0);
        });

        // 计算总数
        long count = taskQuery.count();
        // 设置总数
        page.setTotal(count);
        // 设置数据
        page.setRecords(flowList);
        // 返回
        return page;
    }

    /**
     * 办结事务列表页
     * @param page
     * @param flow
     * @return
     */
    @Override
    public IPage<Flow> selectDonePage(Page<Flow> page, Flow flow) {
        List<Flow> flowList = new LinkedList<>();

        HistoricTaskInstanceQuery doneQuery
                = historyService.createHistoricTaskInstanceQuery().taskAssignee(AuthUtil.getUserId().toString()).finished()
                .includeProcessVariables().orderByHistoricTaskInstanceEndTime().desc();

        if (flow.getProcessDefinitionName() != null) {
            doneQuery.processDefinitionName("%"+flow.getTaskName()+"%");
        }

        Long current = (page.getCurrent() - 1) * page.getSize();
        Long size = page.getSize();
        // 查询列表
        List<HistoricTaskInstance> doneList = doneQuery.listPage(Integer.parseInt(current.toString()), Integer.parseInt(size.toString()));


        doneList.forEach(historicTaskInstance -> {
            Flow flow0 = new Flow();
            flow0.setTaskId(historicTaskInstance.getId());
            flow0.setTaskDefinitionKey(historicTaskInstance.getTaskDefinitionKey());
            flow0.setTaskName(historicTaskInstance.getName());
            flow0.setAssignee(historicTaskInstance.getAssignee());
            flow0.setCreateTime(historicTaskInstance.getCreateTime());
            flow0.setExecutionId(historicTaskInstance.getExecutionId());
            flow0.setHistoryTaskEndTime(historicTaskInstance.getEndTime());
            flow0.setVariables(historicTaskInstance.getProcessVariables());



            //查询流程定义信息
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(historicTaskInstance.getProcessDefinitionId())
                    .singleResult();

            flow0.setCategory(processDefinition.getCategory());
            flow0.setProcessDefinitionId(processDefinition.getId());
            flow0.setProcessDefinitionName(processDefinition.getName());
            flow0.setProcessDefinitionKey(processDefinition.getKey());
            flow0.setProcessDefinitionVersion(processDefinition.getVersion());
            flow0.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
            flow0.setHistoryProcessInstanceId(historicTaskInstance.getProcessInstanceId());

            // 历时任务流程实例
            HistoricProcessInstance historicProcessInstance
                    = historyService.createHistoricProcessInstanceQuery().
                    processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult();
            if (null!=historicProcessInstance) {
                if (null!= historicProcessInstance.getBusinessKey() &&
                 !historicProcessInstance.getBusinessKey().equals("")) {
                    String[] businessKey = historicProcessInstance.getBusinessKey().split(":");
                    flow0.setBusinessTable(businessKey[0]);
                    flow0.setBusinessId(businessKey[1]);
                }

                //流程发起人
                flow0.setCreateUserName(userService.getById(historicProcessInstance.getStartUserId()).getRealName());

                // Status
                if (historicProcessInstance.getEndActivityId() != null) {
                    flow0.setProcessIsFinished("finished");
                } else {
                    flow0.setProcessIsFinished("unfinished");
                }
            }

            flow0.setStatus("finish");

            flowList.add(flow0);
        });
        // 计算总数
        long count = doneQuery.count();
        // 设置总数
        page.setTotal(count);
        page.setRecords(flowList);
        //返回
        return page;
    }

    /**
     * 历史流转列表
     * @param flow
     * @return
     */
    @Override
    public List<Flow> historyList(Flow flow) {
        //查询历史流程实例
        List<HistoricActivityInstance> historicActivityInstanceList
                = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(flow.getProcessInstanceId())
                .orderByHistoricActivityInstanceStartTime()
                .asc()
                .orderByHistoricActivityInstanceEndTime()
                .asc()
                .list();

        List<Flow> flowList = new LinkedList<>();

        if (historicActivityInstanceList.size()>0) {
            Map<String, Object> map = new HashMap<>(16);
            //遍历
            historicActivityInstanceList.forEach(historicActivityInstance -> {
                Flow flows = new Flow();

                //任务名称/开始，结束，审批
                flows.setHistoryActivityId(historicActivityInstance.getActivityId());
                flows.setHistoryActivityName(historicActivityInstance.getActivityName());
                //开始时间，结束时间
                flows.setCreateTime(historicActivityInstance.getStartTime());
                flows.setEndTime(historicActivityInstance.getEndTime());

                //首先找到startEvent
                if (!StringUtils.isBlank(historicActivityInstance.getActivityType()) &&
                historicActivityInstance.getActivityType().equals("startEvent")){
                    //任务发起人信息
                    List<HistoricProcessInstance> processInstanceList
                            = historyService.createHistoricProcessInstanceQuery().processInstanceId(flow.getProcessInstanceId()).
                            orderByProcessInstanceStartTime().asc().list();
                    if (processInstanceList.size() > 0) {
                        if (!StringUtils.isBlank(processInstanceList.get(0).getStartUserId())) {
                            User user = userService.getById(processInstanceList.get(0).getStartUserId());
                            if (user != null) {
                                flows.setCreateUserName(user.getRealName());
                            }
                        }
                    }
                }
                //userTask
                if (!StringUtils.isBlank(historicActivityInstance.getActivityType()) &&
                        historicActivityInstance.getActivityType().equals("userTask")){
                    //批复意见信息 comment
                    if (!StringUtils.isBlank(historicActivityInstance.getTaskId())){
                        List<Comment> comments = taskService.getTaskComments(historicActivityInstance.getTaskId());
                        flows.setComment(comments.get(0).getFullMessage());
                    }
                    //处理人信息
                    if (!StringUtils.isBlank(historicActivityInstance.getAssignee())){
                        User user = userService.getById(historicActivityInstance.getAssignee());
                        if (null!=user) {
                            flows.setAssigneeName(user.getRealName());
                        }
                    }
                    //任务耗时
                    String durationTime = DateUtils.secondToTime(historicActivityInstance.getDurationInMillis() / 1000);
                    flows.setHistoryActivityDurationTime(durationTime);
                }
                //endTask
                if (!StringUtils.isBlank(historicActivityInstance.getActivityType()) &&
                        (historicActivityInstance.getActivityType().equals("startEvent") ||
                                historicActivityInstance.getActivityType().equals("userTask") ||
                                historicActivityInstance.getActivityType().equals("endEvent"))
                ){
                    //加入集合
                    flowList.add(flows);
                }
            });
        }
        //返回
        return flowList;
    }
}
